package com.markpim.dena.opdracht3;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;

public class TrieNode {

	// fields

	private char character;
	private Data trieData;
//	private TrieNode[] children;
//	private ArrayList<TrieNode> children;
	private TreeMap<Character, TrieNode> children;
	private TrieNode parent;

	// constructors

	public TrieNode(TrieNode parent, Data data) {
		this.parent = parent;
		trieData = data;
		children = new TreeMap<Character, TrieNode>();
	}

	public TrieNode(TrieNode parent) {
		this.parent = parent;
		children = new TreeMap<Character, TrieNode>();
	}

	// methods
	public void insert(String s, Data d) {
		s = s.toLowerCase();
		char val = s.charAt(0);

		if (Character.isLetter(s.charAt(0))) {
			if(!children.containsKey(val)) {
				TrieNode child = new TrieNode(this);
				child.character = val;
				children.put(val, new TrieNode(this));
			}

			// als het woord langer is dan 1, dan is het woord nog niet klaar
			// met invoeren
			// anders is het woord klaar en dan kan de completed flag gezet
			// worden
			if (s.length() > 1) {
				children.get(val).insert(s.substring(1), d);
			} else {
				// eerst kijken of er al data bestaat op de positie, zoja, voeg
				// ze samen,
				// zonee, maak een nieuwe
				// hier de completed flag zetten
				if(children.get(val).getData() != null) {
					children.get(val).getData().addPosition(d.getPosition().get(0));
				} else {
					children.get(val).setData(d);
				}
			}
		}

	}

	public TrieNode search(String s) {
		s = s.toLowerCase();
		char val = s.charAt(0);
		if (s.length() > 1) {
			if(children.containsKey(val)) {
				return children.get(val).search(s.substring(1));
			}
		} else {
			// at the last letter
			if(children.get(val).getData() != null) {
				return children.get(val);
			} else {
				//geen data gevonden, verkeerde woord
				return null;
			}
		}
		return null;
	}

	public void deleteAll(String s) {
		TrieNode target = search(s);
		if (target == null) {
			return;
		}
		if(target.children.size() != 0) { //if so, there are children so just set the data to null.
			target.setData(null);
		} else {
			//no children.
			target.setData(null);
			deleteNode(target);
		}
	}

	private void deleteNode(TrieNode child) {
		TrieNode parent = child.parent;
		parent.children.remove(child.character);
		boolean hasNoChild = false;
		if(parent.children.size() != 0) {
			//parent heeft kinderen en kan niet verwijdert worden.
			return;
		} else {
			hasNoChild = true;
		}
		if (hasNoChild && parent.character != 0 && parent.getData() == null) {
			deleteNode(parent);
		}
	}

	// getters
	public int getCount() {
		return getData().getPosition().size();
	}

	public Collection<Data> getAllData(Collection<Data> dataList) {
		for(Map.Entry<Character, TrieNode> e : children.entrySet()) {
			e.getValue().getAllData(dataList);
		}
		if (getData() != null) {
			dataList.add(getData());
		}
		return dataList;
	}

	public char getCharacter() {
		return character;
	}

	public Data getData() {
		return trieData;
	}

	public void setData(Data data) {
		trieData = data;
	}

}
